package com.zmn.oms.dubbo.impl.statistics;

import com.alibaba.fastjson.JSON;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.oms.business.interfaces.es.OrderPayEsBService;
import com.zmn.oms.common.dio.normal.statistics.PayAmountStatQuery;
import com.zmn.oms.common.dro.statistics.OrderPayAmountStatDRO;
import com.zmn.oms.dubbo.interfaces.statistics.StatOrderPayRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.validation.Valid;
import java.util.Date;

/**
 * 类描述：订单支付统计
 *
 * @author heciqi
 * @date 2022/1/12 17:09
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 8000, retries = 0, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class StatOrderPayRemoteServiceImpl implements StatOrderPayRemoteService {
    @Autowired
    private OrderPayEsBService orderPayEsBService;

    @Override
    public ResponseDTO<OrderPayAmountStatDRO> getCiticOrderPayAmountStat(Date payStartTime, Date payEndTime) {
        log.info("订单支付-中信支付统计，入参：{}，{}", DateUtil.toString(payStartTime), DateUtil.toString(payEndTime));

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("payChannelId", PayConsts.PAY_CHANNEL_THIRD_ECITIC)) // 中信支付
                .filter(
                        QueryBuilders.rangeQuery("payTime")
                                .gte(DateUtil.dateFormatToString(payStartTime, DateUtil.FORMAT_DEFAULT))
                                .lte(DateUtil.dateFormatToString(payEndTime, DateUtil.FORMAT_DEFAULT))
                );
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(queryBuilder)
                .withPageable(Pageable.unpaged())
                // 支付总额
                .addAggregation(AggregationBuilders.filter("payAmountFilter", QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("tradeType", PayConsts.PAY_TRADE_TYPE_INTIME)))
                        .subAggregation(AggregationBuilders.sum("payAmountSum").field("amount"))
                )
                // 退款总额
                .addAggregation(AggregationBuilders.filter("refundAmountFilter", QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("tradeType", PayConsts.PAY_TRADE_TYPE_REFUND)))
                        .subAggregation(AggregationBuilders.sum("refundAmountSum").field("amount"))
                )
                .build();
        if (log.isDebugEnabled()) {
            log.debug("OrderEsQuery：{}", queryBuilder.toString());
        }
        Aggregations aggregations = orderPayEsBService.getAggregationsByQuery(build);
        OrderPayAmountStatDRO statDRO  = new OrderPayAmountStatDRO();
        double totalAmountSum = ((ParsedSum) ((ParsedFilter) aggregations.get("payAmountFilter")).getAggregations().get("payAmountSum")).getValue();
        statDRO.setPayAmount((long) totalAmountSum);
        double refundAmount = ((ParsedSum) ((ParsedFilter) aggregations.get("refundAmountFilter")).getAggregations().get("refundAmountSum")).getValue();
        statDRO.setRefundAmount((long) refundAmount);
        if (log.isDebugEnabled()) {
            log.debug("orderPayEsBService.query：{},response:{}", totalAmountSum, JSON.toJSONString(aggregations));
            log.debug("订单支付-中信支付统计，出参：{}", statDRO);
        }
        return ResponseDTO.success(statDRO);
    }

    @Override
    public ResponseDTO<OrderPayAmountStatDRO> getOrderPayAmountStatByQuery(@Valid PayAmountStatQuery query) {
        log.info("订单支付统计，入参：{}", query);

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("payChannelId", query.getChannelId())) // 中信支付
                .filter(
                        QueryBuilders.rangeQuery("payTime")
                                .gte(DateUtil.dateFormatToString(query.getPayStartTime(), DateUtil.FORMAT_DEFAULT))
                                .lte(DateUtil.dateFormatToString(query.getPayEndTime(), DateUtil.FORMAT_DEFAULT))
                );
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(queryBuilder)
                .withPageable(Pageable.unpaged())
                // 支付总额
                .addAggregation(AggregationBuilders.filter("payAmountFilter", QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("tradeType", PayConsts.PAY_TRADE_TYPE_INTIME)))
                        .subAggregation(AggregationBuilders.sum("payAmountSum").field("amount"))
                )
                // 退款总额
                .addAggregation(AggregationBuilders.filter("refundAmountFilter", QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("tradeType", PayConsts.PAY_TRADE_TYPE_REFUND)))
                        .subAggregation(AggregationBuilders.sum("refundAmountSum").field("amount"))
                )
                .build();

        if (log.isDebugEnabled()) {
            log.debug("OrderEsQuery：{}", queryBuilder.toString());
        }
        Aggregations aggregations = orderPayEsBService.getAggregationsByQuery(build);
        OrderPayAmountStatDRO statDRO  = new OrderPayAmountStatDRO();
        double totalAmountSum = ((ParsedSum) ((ParsedFilter) aggregations.get("payAmountFilter")).getAggregations().get("payAmountSum")).getValue();
        statDRO.setPayAmount((long) totalAmountSum);
        double refundAmount = ((ParsedSum) ((ParsedFilter) aggregations.get("refundAmountFilter")).getAggregations().get("refundAmountSum")).getValue();
        statDRO.setRefundAmount((long) refundAmount);
        if (log.isDebugEnabled()) {
            log.debug("orderPayEsBService.query：{},response:{}", totalAmountSum, JSON.toJSONString(aggregations));
            log.debug("订单支付统计，出参：{}", statDRO);
        }

        return ResponseDTO.success(statDRO);
    }
}
